package plus.decl;

import plus.Gripe;
import plus.Symbol;
import plus.TEnv;
import plus.Type;
import plus.TypeSym;

public class D_TypeDef extends Declaration {
	final Template tpl;
	final TypeSpec ts;
	public D_TypeDef(Template tpl, TypeSpec ts) {
		this.tpl = tpl;
		this.ts = ts;
	}
	
	boolean visited = false; // In support of dfs for generating type for 
	public void declare() {
		Symbol<TypeSym> probe = TEnv.findType(tpl.sym.name);
		if (probe == null) {
			// good
			TEnv.add(tpl.sym);
			// Unlike with defining record types, I need to save the definition of the symbol for later.
		} else {
			// Arguably, the said type name should not already exist.
			Gripe.lineNr = tpl.sym.lineNr;
			Gripe.context = this;
			throw new Gripe("Cannot redefine type "+probe);
		}
	}
	public void define() {
		// At this point, we may already be defined:
		if (tpl.sym.definition != null) return;
		
		// But otherwise, prior visitation implies a cycle:
		if (visited) throw new Gripe(tpl.sym.lineNr, "Circular Type Synonyms including "+tpl);
		visited = true;
		
		// For now, we know that the RHS is some kind of nominal type.
		TEnv.enterKappa(tpl);
		Type basis = ts.interpret();
		TEnv.exit();
		
		TEnv.define(tpl, basis);
	}
}
